<?php
//-------------------------------------------------------------------------------------------------------
    require_once($config['app_dir'] . '/classes/stockplot.data.php');
    require_once($config['app_dir'] . '/classes/stockplot.view.php');
    require_once($config['app_dir'] . '/includes/template.class.php');
    require_once($config['app_dir'] . '/includes/date.class.php');
    require_once($config['app_dir'] . '/includes/number.class.php');
    require_once($config['app_dir'] . '/classes/DataLists.class.php');
    require_once($config['app_dir'] . '/classes/tracks.class.php');
    require_once($config['app_dir'] . '/classes/ActiveRecords.class.php');
    //---------------------------------------------------------------------------------------------------
    class GeneratorDashboardForecast {

        static public function GenerateID($aValue) {
            return 'dashboard_forecasts__' . md5(strval($aValue));
        } //GenerateID

    }// class GeneratorLastForecast

    //---------------------------------------------------------------------------------------------------
    class GeneratorLastForecast {

        static public function GenerateID($aValue) {
            return 'last_forecasts__' . md5(strval($aValue));
        } //GenerateID

    }// class GeneratorLastForecast

    //---------------------------------------------------------------------------------------------------

    class objChartPeriod {
            public $flag_find_finish = true;
            public $flag_only_active = false;

            protected $flag_all_systems = false;

            protected $_system = false;
            protected $_trade = false;
            protected $_sql_querys = array();
            protected $flag_build_periods = false;

            protected $_max_dates = false;
            protected $_max_date = false;
            protected $_dates = false;
            protected $periods = false;

            //protected $systemRecord = false;

        public function __construct($aSystem=false) {
            $this->setSystem($aSystem);

            $this->_sqls();
        } //constructor

        public function Dump() {
            echo "\nDump: \n";
            echo "flag_build_periods "; var_dump($this->flag_build_periods);
            echo "flag_all_systems "; var_dump($this->flag_all_systems);
            echo "periods "; var_dump($this->periods);
        } //Dump

        public function setSystem($aSystem=false) {
            if( $aSystem ) {
                if( $this->_system <> $aSystem && !$this->flag_all_systems ) $this->flag_build_periods = false;
                $this->_system = $aSystem;
                $this->_sqls();
            }//if
        } //SetSystem

        public function setTrade($aValue) {
            $this->_trade = $aValue;
            $this->_sqls();
        } //SetTrade

        public function setMaxDate($aDate) {
            $this->_max_date = $aDate;
            $this->_sqls();
            //$this->flag_find_finish = false;
        } //setMaxDate

        protected function BuildDates($aSystem, $aMaxDate, $aOffset) {
            return $this->_dates = objDataBase::GetInstance()->handler->GetOne($this->_sql_querys['dates'], array($aMaxDate, $aSystem, $aOffset) );
        }//buildDates

        protected function Prepare($force=false) {
            if( !$force && $this->flag_build_periods ) return true;

            $dates = objDataBase::GetInstance()->handler->GetAll($this->_sql_querys['max_date']);
            $this->_max_dates = array();
            foreach($dates as $item ) {
                $this->_max_dates[$item['SystemID']] = $item;
            }//foreach
            unset($dates);

            return $this->_max_dates;
        } //Prepare

        public function Build($force=false) {
            if( !$force && $this->flag_build_periods ) return $this->periods;

            $this->Prepare($force);

            $this->flag_build_periods = false;
            $this->periods = array();
            foreach($this->_max_dates as $system=>$mdate ) {

                $result  = array();
                $wresult = array();

                $startWeekend = DateConvert::isWeekendDay($mdate['LastQuote']);
                $iDate = $mdate['LastQuote'] + $mdate['ChartPeriod'];

                while( $iDate && $iDate < $mdate['EndPeriod'] ) {
                    if( DateConvert::isWeekendDay($iDate) ) {
                        if( $startWeekend ) $result[] = $iDate;
                        else $wresult[] = $iDate;
                    } else {
                        if( $startWeekend ) $startWeekend = false;
                        if( !empty($wresult) ) $wresult = array();
                        $result[] = $iDate;
                    }
                    $iDate += $mdate['ChartPeriod'];
                }//while

                if( DateConvert::isWeekendDay($mdate['EndPeriod']) && !empty($wresult) ){
                    $result = array_merge($result, $wresult);
                }
                //----------------------------------------------------------------------------------------------------------------
                $offset = $mdate['ViewPeriod'] / $mdate['ChartPeriod'] - count($result);

                if($offset<0) $offset = 0;

                $this->periods[$system]['start'] = $this->BuildDates(intval($system), intval($mdate['EndPeriod']), intval($offset));

                $this->periods[$system]['startFormated'] = DateConvert::Date('Y-m-d', $this->periods[$system]['start']);
                $this->periods[$system]['finish'] = $mdate['EndPeriod'];
                $this->periods[$system]['finishFormated'] = DateConvert::Date('Y-m-d', $this->periods[$system]['finish']);
            }//for each system
            $this->flag_build_periods = true;

            if( !$this->_system && !$this->_trade ) $this->flag_all_systems = true;

            return $this->periods;
        } //Build

        public function GetPeriod($aSystem=false, $aTrade=false) {
            $this->setSystem($aSystem);
            $this->setTrade($aTrade);
            $this->Build();

            return $this->periods[$this->_system];
        }//GetPeriod

        protected function _sqls() {

            $this->_sql_querys['max_date'] =
                        " SELECT tf.SystemID, ts.ViewPeriod, ts.ChartPeriod, tt.Pair, q.LastQuote, ".
                                " COALESCE(tfa.CountActive,0) as CountActive, ".
                                " MAX(GREATEST(COALESCE(tf.EndTime, tf.CloseTime, tf.BeginTime+ts.ChartPeriod),COALESCE(q.LastQuote, 0))) as EndPeriod ".
                        " FROM vfa_forecast tf ".
                             " LEFT OUTER JOIN fa_systems ts ON (tf.SystemID=ts.SystemID) ".
                             " LEFT OUTER JOIN fa_trades tt ON (tf.TradeID=tt.TradeID) ".
                             " LEFT OUTER JOIN  ".
                                " ( ".
                                  " SELECT  ".
                                     " tts.SystemID, ".
                                     " tts.TradeID, ".
                                     " MAX(tq.Time_T) as LastQuote ".
                                  " FROM fa_quotes tq ".
                                    " LEFT OUTER JOIN fa_trades_systems  tts ON (tts.TradeID=tq.TradeID) ".

                                  " WHERE (1=1) " .

                                  ( $this->_max_date ? "  AND tq.TimeStart<= $this->_max_date " : '' ) .

                                  " GROUP BY tts.SystemID, tts.TradeID ".
                                " ) q ".
                             " ON (tf.SystemId=q.SystemID AND tf.TradeID=q.TradeID) ".

                             " LEFT OUTER JOIN  ( ".
                                  " SELECT  ".
                                     " ttf.SystemID,  ".
                                     " COUNT(*) as CountActive ".
                                  " FROM vfa_forecast ttf ".
                                    " LEFT OUTER JOIN fa_systems tts ON (ttf.SystemID=tts.SystemID) ".
                                  " WHERE ttf.CloseTime is null ".
                                  ( $this->_max_date ? "  AND COALESCE(ttf.EndTime, ttf.CloseTime, ttf.BeginTime+tts.ChartPeriod)<= $this->_max_date " : '' ) .
                                  " GROUP BY ttf.SystemID ".
                             " ) tfa  ".
                             " ON (tfa.SystemID=tf.SystemID) ".

                        " WHERE (1=1) " .
                           ( $this->_max_date ? "  AND COALESCE(tf.EndTime, tf.CloseTime, tf.BeginTime+ts.ChartPeriod)<= $this->_max_date " : '' ) .
                           ( $this->_system ? " AND ts.SystemID=$this->_system" : '' ) .
                           ( $this->_trade ? " AND tf.TradeID=$this->_trade" : '' ) .
                           ( $this->flag_only_active ? " AND CountActive>0 " : '') .
                        " GROUP BY	tf.SystemID ";
            //-------------------------------------------------------------------------------------------------------------------
            $this->_sql_querys['dates'] =
                        " SELECT Time_T ".
                        " FROM fa_quotes q ".
                             " LEFT OUTER JOIN fa_trades_systems  ts ON (ts.TradeID=q.TradeID) ".
                        " WHERE (1=1) ".
                         " AND q.Time_t<? ".
                         " AND ts.SystemID=? ".
                        " ORDER BY q.TradeID, q.Time_t desc ".
                        " LIMIT 6 OFFSET ? ";
        } //_sqls

    } //class ChartPeriod

    //---------------------------------------------------------------------------------------------------
    class objDashboardForecastItem {
            public $forecast_id = false;
            public $pair = false;
            public $system = false;

            public $start = false;
            public $finish = false;

            public $lang = 'en';
            public $caching_time = -1;
            public $image_width = 635;
            public $image_height = 390;
            public $min_period = 259200;

            protected $_sql_querys = array();

        public function __construct($aForecastID, $aLang='en') {
            $this->forecast_id = $aForecastID;
            $this->lang = $aLang;

            $this->_sqls();
        } //constructor


        public function getRate($aPair) {
            $rate = objDataBase::GetInstance()->handler->GetRow($this->_sql_querys['rate'], array(intval($aPair)));
            $rate['decimal'] = NumberConvert::decimal($rate['PipSize']);
            return $rate;
        } //getRate

        protected function Perform() {
            $Forecast = new objForecastView($this->forecast_id);
            $aForecast = $Forecast->Get();

            $this->pair = $aForecast['TradeID'];
            $this->system = $aForecast['SystemID'];

            if( $aForecast['ChartPeriod'] < $this->min_period )$aForecast['ChartPeriod'] = $this->min_period;

            $this->start = $aForecast['BeginForecast'] /*- $aForecast['ChartPeriod'] */- $aForecast['TimeFrame'];
            $this->finish = $aForecast['EndForecast'] + $aForecast['TimeFrame'];
            $times = round($aForecast['ViewPeriod']/$aForecast['ChartPeriod']);

            $td = $this->finish; $cc=0;
            while( $cc<$times ) {
                if( DateConvert::isWeekendDay($td) ) $this->start  -= $aForecast['TimeFrame'];
                else $cc++;
                $td  -= $aForecast['TimeFrame'];
            }//while

            return $aForecast;
        } //Perform

        public function Render($force=true) {
          global $config;
            $id = GeneratorDashboardForecast::GenerateID($this->forecast_id);
            //---------------------------------------------------------------------------------------------------------------
            $Forecast = new objTemplate($this->lang);
            $Forecast->caching = 2;
            $Forecast->cache_lifetime =  $this->caching_time;
            //---------------------------------------------------------------------------------------------------------------
            if( $force || !$Forecast->is_cached('_ForecastItem.tpl', $id) ) {


                $forecast = $this->Perform();

                $rate = $this->getRate($this->pair);
                //---------------------------------------------------------------------------------------------------------------
                $StockModel = new objStockModel($this->pair,
                                                DateConvert::Date('Y-m-d',$this->start),
                                                DateConvert::Date('Y-m-d',$this->finish),
                                                false,
                                                $this->system);
                $StockModel->ExactInterval(true);
                $StockModel->StrongInterval(false);
                //---------------------------------------------------------------------------------------------------------------
                $StockView = new objStockView($this->image_width, $this->image_height);

                $image_filename = $this->lang . '-' . $id . '.' . $StockView->type;
                $image_pathfilename = $config['jpgraph']['cache_dir'] . $image_filename;

                $StockView->HideLogo();
                $StockView->HideNews();
                $StockView->HideCopyright();
                $StockView->SetData($StockModel->getData());
                if( $force ) @unlink($image_pathfilename);
                if( !file_exists($image_pathfilename) ) $StockView->Render($image_pathfilename);
                //---------------------------------------------------------------------------------------------------------------
                $ForecastItem = new objTemplate($this->lang);

                if( $force ) {
                    $Forecast->clear_cache('_ForecastItem.tpl', $id);
                    $ForecastItem->clear_cache('_ForecastItemHeader.tpl', $id);
                    $ForecastItem->clear_cache('_ForecastItemBody.tpl', $id);
                    $ForecastItem->clear_cache('_ForecastItemFooter.tpl', $id);
                } //clear caches

                $ForecastItem->Assign('id', $StockModel->GetID());
                $ForecastItem->Assign('pair', $this->pair);
                $ForecastItem->Assign('start', $start);
                $ForecastItem->Assign('finish', $finish);
                $ForecastItem->Assign('forecast', $StockModel->GetForecastByID($this->forecast_id));
                $ForecastItem->Assign('pair_name', $StockModel->GetPair());
                $ForecastItem->Assign('rate', $rate);
                $ForecastItem->Assign('image', $image_filename);
                $ForecastItem->Assign('t', DateConvert::Date('U')); //
                $ForecastItem->Assign('flagShowRate', 1);
                //---------------------------------------------------------------------------------------------------------------
                $Forecast->Assign('header', $ForecastItem->Fetch('_ForecastItemHeader.tpl', $id));
                $Forecast->Assign('body', $ForecastItem->Fetch('_ForecastItemBody.tpl', $id));
                $Forecast->Assign('footer', $ForecastItem->Fetch('_ForecastItemFooter.tpl', $id)); //, $id

            } //if cache is not  exist

            return $Forecast->Fetch('_ForecastItem.tpl', $id);
        } //Render

        protected function _sqls() {
            //-------------------------------------------------------------------------------------------------------------------
            $this->_sql_querys['rate'] =
                           "SELECT *, FROM_UNIXTIME(r.`Time`, '%Y-%m-%d %H:%i:%s') as RateTime, ".
                                " from_unixtime(r.Time,'%I:%i %p GMT') as RateTimeFormated ".
                            " FROM fa_rates r ".
                                " LEFT OUTER join fa_trades t ON (t.TradeID=r.TradeID ) ".
                            " WHERE r.TradeID=? ORDER BY r.SortIndex ";
            //-------------------------------------------------------------------------------------------------------------------
        } //_sqls

    } //class DashboardForecastItem
    //---------------------------------------------------------------------------------------------------
    class objLastForecastItem {
            public $pair = false;
            public $system = false;
            public $lang = 'en';
            public $caching_time = -1;

            public $image_width = 635;
            public $image_height = 390;

            protected $_sql_querys = array();
            protected $ChartPeriod = false;

        public function __construct($aPair=false, $aSystem=false, $aLang='en') {
            $this->pair = $aPair;
            $this->system = $aSystem;
            $this->lang = $aLang;

            $this->_sqls();
        } //constructor

        public function setChartPeriod(objChartPeriod $aChartPeriod) {
            $this->ChartPeriod = $aChartPeriod;
        } //setChartPeriod

        protected function getPeriod($aSystem) {
            if( !$this->ChartPeriod ) {
                $this->ChartPeriod = new objChartPeriod($aSystem);
                $this->ChartPeriod->Build();
            } //if
            $period = $this->ChartPeriod->GetPeriod($aSystem);
            return $period;
        } //getPeriod

        public function getRate($aPair) {
            $rate = objDataBase::GetInstance()->handler->GetRow($this->_sql_querys['rate'], array(intval($aPair)));
            $rate['decimal'] = NumberConvert::decimal($rate['PipSize']);
            return $rate;
        } //getRate

        public function Render($force=true) {
          global $config;
            $id = GeneratorLastForecast::GenerateID($this->pair . '_' . $this->system);
            //---------------------------------------------------------------------------------------------------------------
            $Forecast = new objTemplate($this->lang);
            $Forecast->caching = 2;
            $Forecast->cache_lifetime =  -1;//$this->caching_time;
            //---------------------------------------------------------------------------------------------------------------
            //$text_cache = '<pre>';
            //$text_cache .=  '|(id='.$id.')cached?='.intval($Forecast->is_cached('_ForecastItem.tpl', $id))."|\n";
            if( $force || !$Forecast->is_cached('_ForecastItem.tpl', $id) ) {

                $rate = $this->getRate($this->pair);
                $period = $this->getPeriod($this->system);
                if( empty($period) ) {
                    //throw new Exception('chart period error');
                    return false;
                }
                $start = $period['startFormated'];
                $finish = $period['finishFormated'];
                //---------------------------------------------------------------------------------------------------------------
                $StockModel = new objStockModel($this->pair, $start, $finish, false, $this->system);
                $StockModel->ExactInterval(true);
                $StockModel->StrongInterval(false);
                //---------------------------------------------------------------------------------------------------------------
                $StockView = new objStockView($this->image_width, $this->image_height);

                $image_filename = $this->lang . '-' . $id . '.' . $StockView->type;
                $image_pathfilename = $config['jpgraph']['cache_dir'] . $image_filename;

                $StockView->HideLogo();
                $StockView->HideNews();
                $StockView->HideCopyright();
                $StockView->SetData($StockModel->getData());
                if( $force ) @unlink($image_pathfilename);
                if( !file_exists($image_pathfilename) ) $StockView->Render($image_pathfilename);
                //---------------------------------------------------------------------------------------------------------------
                $ForecastItem = new objTemplate($this->lang);

                //$ForecastItem->caching = 2;
                //$ForecastItem->cache_lifetime = -1;//$this->caching_time;

                if( $force ) {
                    $Forecast->clear_cache('_ForecastItem.tpl', $id);
                    $ForecastItem->clear_cache('_ForecastItemHeader.tpl', $id);
                    $ForecastItem->clear_cache('_ForecastItemBody.tpl', $id);
                    $ForecastItem->clear_cache('_ForecastItemFooter.tpl', $id);
                } //clear caches

                $ForecastItem->Assign('id', $StockModel->GetID());
                $ForecastItem->Assign('pair', $this->pair);
                $ForecastItem->Assign('start', $start);
                $ForecastItem->Assign('finish', $finish);
                $ForecastItem->Assign('forecast', $StockModel->GetLastForecast());
                $ForecastItem->Assign('pair_name', $StockModel->GetPair());
                $ForecastItem->Assign('rate', $rate);
                $ForecastItem->Assign('image', $image_filename);
                $ForecastItem->Assign('t', 0); //DateConvert::Date('U')
                $ForecastItem->Assign('flagShowRate', 1);
                //---------------------------------------------------------------------------------------------------------------
                $Forecast->Assign('header', $ForecastItem->Fetch('_ForecastItemHeader.tpl', $id));
                $Forecast->Assign('body', $ForecastItem->Fetch('_ForecastItemBody.tpl', $id));
                $Forecast->Assign('footer', $ForecastItem->Fetch('_ForecastItemFooter.tpl', $id)); //, $id
                //$text_cache .=  "|regenerating|\n";
            } //if cache is not  exist
            //$result =  $Forecast->Fetch('_ForecastItem.tpl', $id);

            //$text_cache .=  '|(id='.$id.')cached?='.intval($Forecast->is_cached('_ForecastItem.tpl', $id))."|\n";
            //$text_cache .= '</pre>';
            //---------------------------------------------------------------------------------------------------------------
            //return $text_cache.$result;
            return $Forecast->Fetch('_ForecastItem.tpl', $id);
        } //Render

        protected function _sqls() {
            //-------------------------------------------------------------------------------------------------------------------
            $this->_sql_querys['rate'] =
                           "SELECT *, FROM_UNIXTIME(r.`Time`, '%Y-%m-%d %H:%i:%s') as RateTime, ".
                                " from_unixtime(r.Time,'%I:%i %p GMT') as RateTimeFormated ".
                            " FROM fa_rates r ".
                                " LEFT OUTER join fa_trades t ON (t.TradeID=r.TradeID ) ".
                            " WHERE r.TradeID=? ORDER BY r.SortIndex ";
            //-------------------------------------------------------------------------------------------------------------------
        } //_sqls

    } //class LastForecastItem
    //---------------------------------------------------------------------------------------------------
    class objLastForecastDeamon  {
            public $caching_time = -1;//2*60; //in seconds

            protected $start = false;
            protected $finish = false;

            protected $pairs_systems = array();
            protected $pairs = array();
            protected $systems = array();
            protected $flag_build_periods = false;
            protected $flag_build_pairs = false;
            protected $flag_build_systems = false;
            protected $flag_build_pairs_systems = false;
            protected $_sql_querys = array();

            protected $ChartPeriod = false;

        public function __construct() {
            $this->_sqls();
            $this->ChartPeriod = new objChartPeriod();
        } //function constructor

        public function GenerateID($aValue) {
            return GeneratorLastForecast::GenerateID($aValue);
        } //GenerateID

        protected function BuildPairsSystems($force=false) {
            if( !$force && $this->flag_build_pairs_systems ) return true;

            $listPairsSystems = new objPairsSystems();
            $this->pairs_systems = $listPairsSystems->GetAssocArr();

            $this->flag_build_pairs_systems = true;
            return true;
        } //BuildPairsSystems

        protected function BuildPairs($params=false, $force=false) {
            if( !$force && $this->flag_build_pairs ) return true;
            $trades = objDataBase::GetInstance()->handler->CacheGetAll(3*60, $this->_sql_querys['trades']);//10 minute cache
            $this->pairs = array();
            foreach($trades as $trade) $this->pairs[] = $trade['TradeID'];
            unset($trades);
            $this->flag_build_pairs = true;
        } //BuildPairs

        protected function BuildSystems($force=false) {
            if( !$force && $this->flag_build_systems ) return true;
            $systems = objDataBase::GetInstance()->handler->CacheGetAll(3*60, $this->_sql_querys['systems']);//10 minute cache
            $this->systems = array();
            foreach($systems as $system) $this->systems[] = $system['SystemID'];
            $this->systems[] = 0;
            unset($systems);
            $this->flag_build_systems = true;
        } //BuildSystems

        protected function Prepare() {
            $this->ChartPeriod->Build();
            $this->BuildPairsSystems();

            $this->BuildPairs();
            $this->BuildSystems();
        } //Prepare

        public function RenderItem($pair, $lang='en', $system=false) {
            $ForecastItem = new objLastForecastItem($pair, $system, $lang);
            $ForecastItem->setChartPeriod($this->ChartPeriod);
            return $ForecastItem->Render();
        } //RenderItem

        public function Render() {
            $this->Prepare();
            //-------------------------------------------------------------------------------------------------------------------
            objDashboardForecastsShow::ClearCache();
            //-------------------------------------------------------------------------------------------------------------------
            foreach($this->pairs_systems as $item) {
                //var_dump($item);
                $this->RenderItem($item['TradeID'], 'en', $item['SystemID']);
            }
        } //Render

        protected function _sqls() {
            //-------------------------------------------------------------------------------------------------------------------
            $this->_sql_querys['trades'] =
                'SELECT TradeID FROM fa_trades t ORDER BY t.TradeID';
            //-------------------------------------------------------------------------------------------------------------------
            $this->_sql_querys['systems'] =
                'SELECT SystemID FROM fa_systems s WHERE s.Active=1 ORDER BY s.SystemID';
            //-------------------------------------------------------------------------------------------------------------------
        } //_sqls

    }// class LastForecastDeamon
//-------------------------------------------------------------------------------------------------------
?>
